///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#ifndef __ResourceBackgroundQueue_H__
#define __ResourceBackgroundQueue_H__


#include "OgrePrerequisites.h"
#include "OgreCommon.h"
#include "OgreSingleton.h"
#include "OgreResource.h"
#include "OgreWorkQueue.h"

namespace Ogre {
	
	

	/// Identifier of a background process
	typedef WorkQueue::RequestID BackgroundProcessTicket;

	
	struct BackgroundProcessResult
	{
		/// Whether an error occurred
		bool error;
		/// Any messages from the process
		String message;

		BackgroundProcessResult() : error(false) {}
	};

	
	
	class _OgreExport ResourceBackgroundQueue : public Singleton<ResourceBackgroundQueue>, public MemAlloc_Resource, 
		public WorkQueue::RequestHandler, public WorkQueue::ResponseHandler
	{
	public:
		
		class _OgreExport Listener
		{
		public:
			
			virtual void operationCompleted(BackgroundProcessTicket ticket, const BackgroundProcessResult& result) = 0;
			/// Need virtual destructor in case subclasses use it
			virtual ~Listener() {}

		};

	protected:

		uint16 mWorkQueueChannel;
		
		enum RequestType
		{
			RT_INITIALISE_GROUP = 0,
			RT_INITIALISE_ALL_GROUPS = 1,
			RT_PREPARE_GROUP = 2,
			RT_PREPARE_RESOURCE = 3,
			RT_LOAD_GROUP = 4,
			RT_LOAD_RESOURCE = 5,
			RT_UNLOAD_GROUP = 6,
			RT_UNLOAD_RESOURCE = 7
		};
		
		struct ResourceRequest
		{
			RequestType type;
			String resourceName;
			ResourceHandle resourceHandle;
			String resourceType;
			String groupName;
			bool isManual; 
			ManualResourceLoader* loader;
			NameValuePairList* loadParams;
			Listener* listener;
			BackgroundProcessResult result;

			_OgreExport friend std::ostream& operator<<(std::ostream& o, const ResourceRequest& r)
			{ (void)r; return o; }
		};

		typedef set<BackgroundProcessTicket>::type OutstandingRequestSet;	
		OutstandingRequestSet mOutstandingRequestSet;

		/// Struct that holds details of queued notifications
		struct ResourceResponse
		{
			ResourceResponse(ResourcePtr r, const ResourceRequest& req)
				: resource(r), request(req)
			{}

			ResourcePtr resource;
			ResourceRequest request;

			_OgreExport friend std::ostream& operator<<(std::ostream& o, const ResourceResponse& r)
			{ (void)r; return o; }
		};

		BackgroundProcessTicket addRequest(ResourceRequest& req);

	public:
		ResourceBackgroundQueue();
		virtual ~ResourceBackgroundQueue();

		
		virtual void initialise(void);

		
		virtual void shutdown(void);

		
		virtual BackgroundProcessTicket initialiseResourceGroup(
			const String& name, Listener* listener = 0);

		
		virtual BackgroundProcessTicket initialiseAllResourceGroups( 
			Listener* listener = 0);
		
		virtual BackgroundProcessTicket prepareResourceGroup(const String& name, 
			Listener* listener = 0);

		
		virtual BackgroundProcessTicket loadResourceGroup(const String& name, 
			Listener* listener = 0);


		
		virtual BackgroundProcessTicket unload(
			const String& resType, const String& name, 
			Listener* listener = 0);

		
		virtual BackgroundProcessTicket unload(
			const String& resType, ResourceHandle handle, 
			Listener* listener = 0);

		
		virtual BackgroundProcessTicket unloadResourceGroup(const String& name, 
			Listener* listener = 0);


		
		virtual BackgroundProcessTicket prepare(
			const String& resType, const String& name, 
            const String& group, bool isManual = false, 
			ManualResourceLoader* loader = 0, 
			const NameValuePairList* loadParams = 0, 
			Listener* listener = 0);

		
		virtual BackgroundProcessTicket load(
			const String& resType, const String& name, 
            const String& group, bool isManual = false, 
			ManualResourceLoader* loader = 0, 
			const NameValuePairList* loadParams = 0, 
			Listener* listener = 0);
		
		virtual bool isProcessComplete(BackgroundProcessTicket ticket);

		
		void abortRequest( BackgroundProcessTicket ticket );

		/// Implementation for WorkQueue::RequestHandler
		bool canHandleRequest(const WorkQueue::Request* req, const WorkQueue* srcQ);
		/// Implementation for WorkQueue::RequestHandler
		WorkQueue::Response* handleRequest(const WorkQueue::Request* req, const WorkQueue* srcQ);
		/// Implementation for WorkQueue::ResponseHandler
		bool canHandleResponse(const WorkQueue::Response* res, const WorkQueue* srcQ);
		/// Implementation for WorkQueue::ResponseHandler
		void handleResponse(const WorkQueue::Response* res, const WorkQueue* srcQ);

		
        static ResourceBackgroundQueue& getSingleton(void);
        
        static ResourceBackgroundQueue* getSingletonPtr(void);

	};

	
	

}

#endif

